/*
 * Copyright (c)  2017, ueboot.com
 * All rights reserved.
 * 2017-10-29 11:39:14
 */
package com.ueboot.weishop.admin.controller.order;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ueboot.core.exception.BusinessException;
import com.ueboot.core.http.response.Response;
import com.ueboot.core.utils.DateUtils;
import com.ueboot.weishop.admin.controller.order.vo.OrderFindReq;
import com.ueboot.weishop.admin.controller.order.vo.OrderReq;
import com.ueboot.weishop.admin.controller.order.vo.OrderResp;
import com.ueboot.weishop.entity.order.OrderEntity;
import com.ueboot.weishop.entity.order.OrderEnum;
import com.ueboot.weishop.entity.order.OrderExtensionEntity;
import com.ueboot.weishop.entity.order.OrderIssueEntity;
import com.ueboot.weishop.service.cache.CacheService;
import com.ueboot.weishop.service.order.OrderExtensionService;
import com.ueboot.weishop.service.order.OrderIssueService;
import com.ueboot.weishop.service.order.OrderNewService;
import com.ueboot.weishop.service.order.OrderService;
import com.ueboot.weishop.service.weixin.WXRefundOrderReq;
import com.ueboot.weishop.service.weixin.WXRefundOrderResp;
import com.ueboot.weishop.service.weixin.WeiXinService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;
import java.util.Map;


/**
 * Created by yangkui  on 2017-10-29 11:39:14.
 *
 * @author yangkui fanjiapeng
 * @since 2.0 by autocode
 */
@Slf4j
@RestController
@RequestMapping(value = "/order")
public class OrderController {

    private static final org.slf4j.Logger logger = LoggerFactory.getLogger(OrderController.class);

    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderExtensionService orderExtensionService;

    @Autowired
    private OrderIssueService orderIssueService;

    @Autowired
    private WeiXinService weiXinService;

    @Autowired
    private OrderNewService orderNewService;

    @Autowired
    private CacheService cacheService;

    @RequiresPermissions("order:read")
    @RequestMapping(value = "/page", method = RequestMethod.POST)
    public Response<Page<OrderResp>> page(@PageableDefault(value = Integer.MAX_VALUE, sort = {"id"}, direction = Sort.Direction.DESC) Pageable pageable,
                                          @RequestBody(required = false) OrderFindReq request,
                                          @RequestParam(value = "keyWord", required = false) String keyWord) {

        OrderEntity orderEntity = new OrderEntity();
        BeanUtils.copyProperties(request, orderEntity);
        orderEntity.setGoodsName(keyWord);
        Page<OrderEntity> entities = orderNewService.pagingSearch(pageable, orderEntity, request.getPayTimeStart(), request.getPayTimeEnd());
        Page<OrderResp> body = entities.map(entity -> {
            OrderResp resp = new OrderResp();
            BeanUtils.copyProperties(entity, resp);
            if (null != entity.getOrderTime()) {
                resp.setOrderTime(DateUtils.format(entity.getOrderTime(), DateUtils.FORMAT_DATE_TIME_DEFAULT));
            }
            if (null != entity.getPayTime()) {
                resp.setPayTime(DateUtils.format(entity.getPayTime(), DateUtils.FORMAT_DATE_TIME_DEFAULT));
            }
            if (null != entity.getRefundTime()) {
                resp.setRefundTime(DateUtils.format(entity.getRefundTime(), DateUtils.FORMAT_DATE_TIME_DEFAULT));
            }
            if (null != entity.getApplyRefundTime()) {
                resp.setApplyRefundTime(DateUtils.format(entity.getApplyRefundTime(), DateUtils.FORMAT_DATE_TIME_DEFAULT));
            }
            OrderExtensionEntity extensionEntity = orderExtensionService.findByOrderNo(entity.getOrderNo());
            resp.setCustomerVin(extensionEntity.getCustomerVin());
            resp.setTargetDealer(extensionEntity.getTargetDealer());
            resp.setCarType(extensionEntity.getCarType());
            resp.setName(entity.getCustomer().getName());
            resp.setMobileAudit(entity.getCustomer().getMobile());
            resp.setPayAmount(entity.getPayAmount()/100);
            resp.setInvalid(new Date().after(entity.getPayValidTime()));
            return resp;
        });

        return new Response<>(body);
    }

    @RequiresPermissions("order:read")
    @RequestMapping(value = "/find", method = RequestMethod.POST)
    public Response<List<OrderResp>> find(@RequestBody(required = false) OrderFindReq request,
                                          @RequestParam(value = "keyWord", required = false) String keyWord) {
        OrderEntity orderEntity = new OrderEntity();
        BeanUtils.copyProperties(request, orderEntity);
        orderEntity.setGoodsName(keyWord);
        List<OrderEntity> entities = orderNewService.findSearch(orderEntity, request.getPayTimeStart(), request.getPayTimeEnd());

        List<OrderResp> bodyResp = Lists.newLinkedList();
        entities.forEach(entity -> {
            OrderResp resp = new OrderResp();
            BeanUtils.copyProperties(entity, resp);
            if (null != entity.getOrderTime()) {
                resp.setOrderTime(DateUtils.format(entity.getOrderTime(), DateUtils.FORMAT_DATE_TIME_DEFAULT));
            }
            if (null != entity.getPayTime()) {
                resp.setPayTime(DateUtils.format(entity.getPayTime(), DateUtils.FORMAT_DATE_TIME_DEFAULT));
            }
            if (null != entity.getRefundTime()) {
                resp.setRefundTime(DateUtils.format(entity.getRefundTime(), DateUtils.FORMAT_DATE_TIME_DEFAULT));
            }
            if (null != entity.getApplyRefundTime()) {
                resp.setApplyRefundTime(DateUtils.format(entity.getApplyRefundTime(), DateUtils.FORMAT_DATE_TIME_DEFAULT));
            }
            bodyResp.add(resp);
        });
        return new Response<>(bodyResp);
    }

    /**
     * 保存退款状态和退款原因
     */
    @RequiresPermissions("order:saverefund")
    @RequestMapping(value = "/saverefund", method = RequestMethod.POST)
    public Response<Void> saverefund(@RequestBody OrderReq req) {
        OrderEntity entity = orderService.get(req.getId());
        String categoryCode = entity.getCategoryCode();
        if (OrderEnum.REFUND_STATUS_2.equals(req.getRefundStatus())) {
            if ("102,103,104".contains(categoryCode)) {
                logger.info("订单为{},不退款", entity.getCategoryName());
                throw new BusinessException(entity.getCategoryName() + "活动，退款操作！");
            } else {
                //退款成功
                //根据orderNo查询发送DMS的组装数据 OrderIssueEntity，像DMS发起退货申请请求。将反馈结果保存
                //查询历史发送DMS订单信息
                List<OrderIssueEntity> orderIssueList = orderIssueService.findByOrderNo(req.getOrderNo());
                if (orderIssueList.size() > 0) {
                    List<Map<String, String>> reqList = Lists.newLinkedList();
                    orderIssueList.forEach(orderIssue -> {
                        Map<String, String> reqMap = Maps.newHashMap();
                        reqMap.put("SEQ_NO", orderIssue.getSeqNo());
                        reqMap.put("NAME", orderIssue.getName());
                        reqMap.put("VIN", orderIssue.getVin());
                        reqMap.put("CAMPAIGN_CODE", orderIssue.getCampaignCode());
                        reqMap.put("VALID_BEGIN_DATE", orderIssue.getValidBeginDate());
                        reqMap.put("VALID_END_DATE", orderIssue.getValidEndDate());
                        reqMap.put("TARGET_DEALER", orderIssue.getTargetDealer());
                        reqMap.put("USE_DEALER", "");
                        reqMap.put("AMOUNT", orderIssue.getAmount());
                        reqMap.put("USE_AMOUNT", "0.0");
                        reqMap.put("LOWEST_AMOUNT", "0.0");
                        reqMap.put("LIMIT_DEDUCT", orderIssue.getLimitDeduct());
                        reqMap.put("IS_CANCEL", OrderIssueEntity.CANCER_2);
                        reqList.add(reqMap);
                    });
                    String responseMessage = orderIssueService.sendDmsCoupon(reqList);
                    Map dmsResp = JSON.parseObject(responseMessage, Map.class);

                    if (!"OK".equals(dmsResp.get("code"))) {
                        logger.info("DMS回传接口异常！FC不做任何处理！{}", dmsResp.get("message"));
                        throw new BusinessException("DMS回传接口异常！" + dmsResp.get("message"));
                    }
                    Map dmsRespBoy = JSON.parseObject(dmsResp.get("body") + "", Map.class);
                    if (!"0".equals(dmsRespBoy.get("status_code"))) {
                        logger.info("DMS回传接口返回数据异常！FC不做任何处理！{}", JSON.toJSON(dmsRespBoy));
                        throw new BusinessException("DMS回传接口返回数据异常！" + dmsRespBoy);
                    }
                    StringBuffer sb = new StringBuffer(); //审核原因
                    Date sendDmsTime = new Date();
                    for (OrderIssueEntity orderIssue : orderIssueList) {
                        orderIssue.setDmsResult("失败");//默认设置为DMS请求失败
                        orderIssue.setCancel(OrderIssueEntity.CANCER_2);//设置请求DMS的取消操作类型，1：自动取消代金券
                        orderIssue.setLastSendDmsTime(sendDmsTime);

                        Integer sendCount = orderIssue.getSendDmsCount();
                        if (sendCount == null) {
                            sendCount = 0;
                        }
                        orderIssue.setSendDmsCount(sendCount + 1);
                        String sendHistory = orderIssue.getSendDmsHistory();
                        if (sendHistory == null) {
                            sendHistory = "";
                        }
                        List<Map<String, String>> contentMapList = (List<Map<String, String>>) dmsResp.get("content");
                        if (contentMapList == null || contentMapList.size() == 0) {
                            sendHistory += "【发送时间：" + DateUtils.format(sendDmsTime, DateUtils.FORMAT_DATE_TIME_DEFAULT) + "，第" + (orderIssue.getSendDmsCount() + 1) + "次发送，Cancer:1,发送结果：发送成功】";
                            orderIssue.setDmsResult("发送成功");
                        } else {
                            Map<String, String> contentMap = contentMapList.get(0);
                            String dmsResult = contentMap.get("ERROR_MSG");
                            orderIssue.setDmsResult(contentMap.get("ERROR_MSG"));
                            sendHistory += "【发送时间：" + DateUtils.format(sendDmsTime, DateUtils.FORMAT_DATE_TIME_DEFAULT) + "，第" + (orderIssue.getSendDmsCount() + 1) + "次发送，Cancer:1，DMS反馈：" + dmsResult + "】";
                            sb.append(dmsResult);
                        }
                        orderIssue.setSendDmsHistory(sendHistory);
                        orderIssueService.save(orderIssue);
                    }
                    if (StringUtils.isNotEmpty(sb.toString())) {
                        throw new BusinessException(sb.toString());
                    }
                }
                entity.setExtStatus(OrderEnum.EXT_STATUS_2);
            }
            WXRefundOrderReq wxReq = new WXRefundOrderReq();
            wxReq.setTransactionId(entity.getTransactionNo());
            wxReq.setOrderNo(entity.getOrderNo());
            wxReq.setOrderPrice(entity.getPayAmount());
            wxReq.setProductName(entity.getGoodsName());
            wxReq.setNotSettle(req.getSettle());
            WXRefundOrderResp refundOrderResp = weiXinService.refundOrder(wxReq);
            if (!WXRefundOrderResp.CODE_0.equalsIgnoreCase(refundOrderResp.getResultCode())) {
                throw new BusinessException("退款失败，" + refundOrderResp.getErrorMsg());
            }
            entity.setRefundTime(new Date());
            entity.setRefundStatus(OrderEnum.REFUND_STATUS_2);
            entity.setRefundAuditResult("退款成功");
        } else {
            entity.setRefundStatus(OrderEnum.REFUND_STATUS_3);
            entity.setRefundAuditResult(req.getRefundAuditResult());
        }
        orderService.save(entity);
        return new Response<>();
    }

    @RequiresPermissions("order:save")
    @RequestMapping(value = "/save", method = RequestMethod.POST)
    public Response<Void> save(@RequestBody OrderReq req) {
        OrderEntity entity = null;
        if (req.getId() == null) {
            entity = new OrderEntity();
        } else {
            entity = orderService.get(req.getId());
        }
        BeanUtils.copyProperties(req, entity);
        orderService.save(entity);
        return new Response<>();
    }

    @RequiresPermissions("order:delete")
    @RequestMapping(value = "/delete", method = RequestMethod.POST)
    public Response<Void> delete(Long[] id) {
        orderService.delete(id);
        return new Response<>();
    }

    @RequiresPermissions("order:read")
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public Response<OrderResp> get(@PathVariable Long id) {
        OrderEntity entity = orderService.get(id);
        OrderResp resp = new OrderResp();
        BeanUtils.copyProperties(entity, resp);
        return new Response<>(resp);
    }


    @RequiresPermissions("order:read")
    @RequestMapping(value = "/invalid/{id}", method = RequestMethod.POST)
    public Response<Void> invalid(@PathVariable Long id) {
        OrderEntity entity = orderService.get(id);
        entity.setOrderStatus(OrderEnum.ORDER_STATUS_3);


        String rollBackKey = entity.getActivitySN()+":"+entity.getActivityFullPathIds();
        if(!StringUtils.isEmpty(entity.getCountKey())){
            rollBackKey +=":"+entity.getCountKey();
        }
        cacheService.putRollbackOrder(rollBackKey, entity.getOrderNo(), entity.getGoodsCount());
        //修改订单状态
        log.info("订单号:{},进行回滚后，设置状态为已过期!", entity.getOrderNo());
        orderService.updateOrderStatus(entity.getOrderNo(), OrderEnum.ORDER_STATUS_3);
        return new Response<>();
    }

}
